package org.demo.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.handlers.StrictFill;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.function.Supplier;

/**
 * MetaObjectHandler: 用于处理实体对象的公共字段在插入和更新操作时的元对象字段填充。
 * 例如，createTime、updateTime等一般都是对象的公共字段，如果我们需要这些字段进行自动填充时，就可以定义在这里。
 *
 * @author yexi
 */
@Component
public class CustomMetaObjectHandler implements MetaObjectHandler {
    /**
     * insertFill: 在插入操作时调用，用于填充实体对象的元对象字段，比如创建时间。
     *
     * @param metaObject 元对象
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
    }

    /**
     * updateFill: 在更新操作时调用，用于填充实体对象的元对象字段，比如更新时间。
     * strictFillStrategy: 严格模式填充策略。默认有值不覆盖，如果提供的值为null也不填充。
     *
     * @param metaObject 元对象
     * @see MetaObjectHandler#strictFillStrategy(MetaObject, String, Supplier)
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
    }

    /**
     * strictFill: 严格填充，strictInsertFill和strictUpdateFill的底层。
     * 只针对非主键的字段，只有该表字段注解了 fill属性(@TableField注解当中) 并且 字段名和字段属性 能匹配到才会进行填充。
     * 匹配到之后默认调用 strictFillStrategy。
     *
     * @param insertFill  是否验证在 insert 时填充
     * @param tableInfo   cache 缓存
     * @param metaObject  metaObject meta object parameter
     * @param strictFills 填充信息
     */
    @Override
    public MetaObjectHandler strictFill(boolean insertFill, TableInfo tableInfo, MetaObject metaObject, List<StrictFill<?, ?>> strictFills) {
        return MetaObjectHandler.super.strictFill(insertFill, tableInfo, metaObject, strictFills);
    }

    /**
     * 严格模式填充策略。默认有值不覆盖，如果提供的值为 null 也不填充。
     * TIPS: 如果需要即便有值也要覆盖，则可以考虑重写此方法。
     */
    @Override
    public MetaObjectHandler strictFillStrategy(MetaObject metaObject, String fieldName, Supplier<?> fieldVal) {
        return MetaObjectHandler.super.strictFillStrategy(metaObject, fieldName, fieldVal);
    }
}
